﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DLinkedList
{

    


    public class ForwardList<T> : ICollection<T>
    {
        public ForwardList(){}

        ~ForwardList(){}




        public class Node<T>
        {
            public T value = default(T); //T kan vara antingen värde- eller referenstyp
            //ex. om T är int blir deafaultvärdet 0, om string en tom sträng
            public Node<T> next = null;
            public Node<T> prev = null;

            public Node()
            {

            }

            public Node(T value) //konstruktor där värdedelen fylls i
            {
                this.value = value;
            }

            ~Node()
            {
            }

        }


        private Node<T> head = null;

        public bool IsEmpty()
        {
            return head == null;
        }

        public void Add(T item)
        {
            throw new NotImplementedException();
        }

        public void Clear()
        {
            head = null;
        }

        public bool Contains(T item)
        {
            foreach (var value in this)
            {
                if (value.Equals(item))
                    return true;
            }
            return false;
        }

        public T Find(T item)
        {
            foreach (var value in this)
            {
                if (value.Equals(item))
                    return value;
            }
            return default(T);
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            throw new NotImplementedException();
        }

        public int Count
        {
            get {
                Node<T> node = head;
                int i = 0;
                while (node != null)
                {
                    node = node.next;
                    i++;
                }
                return i;
            }
        }

        public void AddFirst(T item)
        {
            Node<T> n = new Node<T>(item);

            if (head == null)
            {
                head = n;
            }
            else
            {
                n.next = head; //nya noden får tidigare första noden som next
                head = n; //head pekar nu på nya noden
                n.next.prev = n; //tidigare första noden får nya noden som prev
            }
        }

        public Node<T> First
        {
            get
            {
                if (head == null)
                    throw new Exception("Listan är tom");
                return head;
            }
        }

        public void AddLast(T item)
        {
            Node<T> n = new Node<T>(item);

            if (head == null)
            {
                head = n;
            }
            else
            {
                n.prev = Last; //nya noden får tidigare sista noden som prev
                Last.next = n; //tidigare sista noden får nya noden som next
            }
        }

        public Node<T> Last
        {
            get
            {
                if (head == null)
                    throw new Exception("Listan är tom");
                Node<T> node = head;
                while (node.next != null)
                {
                    node = node.next;
                }
                return node;
            }
        }

        public void RemoveLast()
        {
            if (head == null)
                throw new Exception("Listan är tom");
            Node<T> node = head;
            while (node.next != null)
            {
                node = node.next;
            }
            if (node == head)
            {
                head = null;
            }
            else
            {
                node.prev.next = null;
            }
        }

        public void RemoveFirst()
        {
            if (head == null)
            {
                throw new Exception("Listan är tom");
            }
            Node<T> node = head;
            head = node.next;
            if (node.next != null)
            {
                node.next.prev = null;
            }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(T item)
        {
            if (head == null)
                throw new Exception("Listan är tom");
            Node<T> node = head;
            while (node != null)
            {
                if (node.value.Equals(item))
                {
                    if (head == node)
                    {
                        head = node.next;
                    }
                    else
                    {
                        node.prev.next = node.next;
                    }
                    if (node.next != null)
                    {
                        node.next.prev = node.prev;
                    }
                    return true;
                }
                node = node.next;
            }
            return false;
        }

        //knyckt från föreläsningen
        public IEnumerator<T> GetEnumerator() 
        {
            Node<T> n = head;
            while (n != null)
            {
                yield return n.value;
                n = n.next;
            }
        }

        //knyckt från föreläsningen
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        } 


    }
}
